package com.game;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class MGFileHander extends Thread
{

	private boolean autoRestart = false;
	private ServerSocket mServerSocket;
	private int bufferSize = 1024;
	private int svrPort = 6620;
	private String mInBoxPath = "";

	public class SendFileThread extends Thread
	{
		byte byteBuffer[] = new byte[bufferSize];
		String remoteIPString = null;
		int port;
		Socket tempSocket;
		OutputStream outSocket;
		InputStream inSocket;
		private String mfilePath;

		public SendFileThread(String remoteIPString, int port)
		{
			try
			{
				this.remoteIPString = remoteIPString;
				this.port = port;

			}
			catch (Exception ex)
			{
				ex.printStackTrace();
			}
		}

		@Override
		public void run()
		{
			try
			{
				this.tempSocket = new Socket(this.remoteIPString, this.port);
				System.out.println("与服务器连接成功!");

				int amount;
				outSocket = tempSocket.getOutputStream();
				inSocket = tempSocket.getInputStream();

				writeString(outSocket, getFileInfo(mfilePath));
				sleep(500);

				String command = readString(inSocket);
				if (command.contains("ready=1"))
				{
					File readySendFile = new File(mfilePath);
					FileInputStream fis = new FileInputStream(readySendFile);
					System.out.println("开始发送文件...");
					while ((amount = fis.read(byteBuffer)) != -1)
					{
						outSocket.write(byteBuffer, 0, amount);
						System.out.println("文件发送中...");
					}
					System.out.println("Send File complete");
					fis.close();

					readySendFile.delete();

				}

			}
			catch (Exception e)
			{
				System.out.println(e.toString());
				e.printStackTrace();
			}
			finally
			{
				if (tempSocket.isConnected())
				{
					try
					{
						inSocket.close();
						outSocket.close();
						tempSocket.close();
					}
					catch (Exception ex2)
					{
						ex2.printStackTrace();
					}
				}
			}

		}

		public void execute(String filePath)
		{
			try
			{
				mfilePath = filePath;
				// outFile = new RandomAccessFile(filePath, "r");

				this.start();
			}
			catch (Exception ex)
			{
				// TODO Auto-generated catch block
				ex.printStackTrace();
			}
		}
	}

	private class SaveFile2Disk extends Thread
	{

		private Socket _socket = null;
		private InputStream _is = null;
		private OutputStream _os = null;

		public SaveFile2Disk(Socket socket)
		{
			this._socket = socket;
			try
			{
				_is = _socket.getInputStream();
				_os = _socket.getOutputStream();
				System.out.println(socket.getInetAddress() + " is connected.");
			}
			catch (Exception ex)
			{
				// TODO: handle exception
				ex.printStackTrace();
			}
		}

		@Override
		public void run()
		{

			try
			{

				File inbox = new File(mInBoxPath);
				if (inbox.isDirectory())
				{
					String command = readString(_is);

					if (command == null || !command.contains("MoleQInfo"))
					{
						return;
					}
					String fileName = getTagValue(command, "FileName");
					String fileSize = getTagValue(command, "FileLength");

					sleep(200);

					writeString(_os, "ready=1");

					receiveFile(_is, fileName, fileSize);
				}

			}
			catch (Exception ex)
			{
				ex.printStackTrace();
			}
			finally
			{
				if (_socket.isConnected())
				{
					try
					{
						_is.close();
						_os.close();
						_socket.close();
					}
					catch (Exception ex2)
					{
						ex2.printStackTrace();
					}
				}
			}
		}
	}

	private String getFileInfo(String filePath) throws Exception
	{
		File tempFile = new File(filePath);
		String fileName = tempFile.getName();
		long fileSize = tempFile.length();
		String fileInfos;
		fileInfos = "MoleQInfo";
		fileInfos += "<FileName>" + fileName + "</FileName>";
		fileInfos += "<FileLength>" + fileSize + "</FileLength>";
		return fileInfos;
	}

	private void writeString(OutputStream os, String context)
			throws IOException
	{
		OutputStreamWriter osw = new OutputStreamWriter(os);
		BufferedWriter writer = new BufferedWriter(osw);

		writer.write(context);
		writer.flush();
	}

	private String readString(InputStream is) throws IOException
	{
		String result = "";

		byte[] buffer = new byte[bufferSize];

		String recBuffer = "";
		int readCount = 0;
		while ((readCount = is.read(buffer, 0, bufferSize)) > 0)
		{

			recBuffer += new String(buffer, 0, readCount);
			if (readCount < bufferSize)
			{
				System.out.println("receive end ->" + recBuffer);
				result = recBuffer;
				break;
			}
		}
		return result;
	}

	private void receiveFile(InputStream is, String fileName, String fileSize)
			throws Exception
	{

		byte byteBuffer[] = new byte[bufferSize];
		long totalCount = 0;
		int count = 0;
		long filesize = Long.valueOf(fileSize);
		BufferedInputStream bis = new BufferedInputStream(is);

		File recfile = new File(mInBoxPath, fileName + ".temp");
		FileOutputStream fos = new FileOutputStream(recfile);
		BufferedOutputStream bos = new BufferedOutputStream(fos);

		do
		{
			count = bis.read(byteBuffer);
			bos.write(byteBuffer, 0, count);
			totalCount += count;
		}
		while (totalCount < filesize);
		bos.flush();
		bos.close();

		if (recfile.exists())
		{
			File newFile = new File(mInBoxPath, fileName);

			if (newFile.exists())
				newFile.delete();

			recfile.renameTo(newFile);
		}

	}

	public void sendFile(String fileName, String ipAddress, int port)
	{
		SendFileThread task = new SendFileThread(ipAddress, port);
		task.execute(fileName);
	}

	protected void sleep(int time)
	{
		try
		{
			Thread.sleep(time);
		}
		catch (InterruptedException ex)
		{
			// TODO Auto-generated catch block
			ex.printStackTrace();
		}
	}

	public String getTagValue(String str, String tag)
	{
		String result = "";
		String start, end;
		int i, j;

		if (str.equals("") || tag.equals(""))
			return result;

		start = "<" + tag + ">";
		end = "</" + tag + ">";

		i = str.indexOf(start);
		j = str.indexOf(end);
		if (i >= 0 && j >= 0)
		{
			result = str.substring(i + start.length(), j);
		}
		return result;
	}

	public void start(int port)
	{
		svrPort = port;
		autoRestart = true;
		super.start();
	}

	@Override
	public void run()
	{
		while (autoRestart)
		{

			try
			{
				mServerSocket = new ServerSocket(svrPort);
				System.out.println("Receive Server started ...");

				while (mServerSocket != null && !mServerSocket.isClosed())
				{
					Socket cilentSocket = mServerSocket.accept();
					cilentSocket.setSoTimeout(1500);
					new SaveFile2Disk(cilentSocket).start();
				}
			}
			catch (Exception ex)
			{
				System.out.println("Server shutdown. ->" + ex.getMessage());
			}
			finally
			{
				try
				{
					if (mServerSocket != null)
					{
						mServerSocket.close();
					}
				}
				catch (IOException ex)
				{
					// TODO Auto-generated catch block
					ex.printStackTrace();
				}
			}
		}
	}

	public void setInBox(String path)
	{
		File inbox = new File(path);
		if (inbox.isDirectory())
		{
			mInBoxPath = path;
		}
		else
		{
			mInBoxPath = "";
		}
	}

	public static void main(String[] args)
	{
		MGFileHander fh = new MGFileHander();
		fh.setInBox("C:\\");
		fh.start(6600);
	}

	public void release()
	{
		autoRestart = false;
		try
		{
			if (mServerSocket != null)
			{
				mServerSocket.close();
			}
		}
		catch (IOException ex)
		{
			// TODO Auto-generated catch block
			ex.printStackTrace();
		}

	}
}
